package com.ctshk.rpc.finance.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.SysApprovalType;
import com.ctshk.common.enums.SystemBusinessType;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.CharUtil;
import com.ctshk.common.utils.DateUtil;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.finance.dto.bill.*;
import com.ctshk.rpc.finance.dto.onaccount.OnAccountUsageCountDTO;
import com.ctshk.rpc.finance.entity.*;
import com.ctshk.rpc.finance.json.ClientInfoJson;
import com.ctshk.rpc.finance.json.FileJson;
import com.ctshk.rpc.finance.mapper.*;
import com.ctshk.rpc.finance.req.bill.*;
import com.ctshk.rpc.finance.service.IFinanceBillCheckService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 客户对账 服务实现类
 * </p>
 *
 * @author 叶冠峰
 * @since 2021-03-26
 */
@DubboService
public class FinanceBillCheckServiceImpl extends ServiceImpl<FinanceBillCheckMapper, FinanceBillCheck> implements IFinanceBillCheckService {

    @Autowired
    private FinanceBillCheckMapper billCheckMapper;
    @Autowired
    private FinanceBillCheckDetailMapper billCheckDetailMapper;
    @Autowired
    private FinanceBillMapper billMapper;
    @Autowired
    private FinanceAdvancePaymentMapper advancePaymentMapper;
    @Autowired
    private FinanceOnAccountUsageRecordMapper onAccountUsageRecordMapper;
    @Autowired
    private FinanceOffAccountApplyDetailMapper offAccountApplyDetailMapper;
    @Autowired
    private FinanceOnAccountMapper onAccountMapper;


    @DubboReference
    private ISysApprovalService sysApprovalService;
    @DubboReference
    private ISysUserService sysUserService;



    /**
     * 列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<BillCheckListDTO>> list(BillCheckListReq req) {
        Page<FinanceBillCheck> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<FinanceBillCheck> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(req.getApprovalStatus() != null,"approval_status",req.getApprovalStatus());
        queryWrapper.eq(req.getCreateId() != null,"create_id",req.getCreateId());
        queryWrapper.eq("is_deleted",0);
        queryWrapper.between(req.getGmtCreateBegin() != null && req.getGmtCreateEnd() != null,"gmt_create",req.getGmtCreateBegin(),req.getGmtCreateEnd());
        queryWrapper.like(StringUtils.isNotBlank(req.getCheckNumber()),"check_number",req.getCheckNumber());
        queryWrapper.like(StringUtils.isNotBlank(req.getCustomerName()),"customer_name",req.getCustomerName());
        queryWrapper.orderByDesc("gmt_create");
        Page<FinanceBillCheck> page = billCheckMapper.selectPage(iPage, queryWrapper);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        List<BillCheckListDTO> list = new ArrayList<>();
        page.getRecords().forEach(item -> {
            BillCheckListDTO dto = EntityUtil.copy(item,BillCheckListDTO.class);
            //获取部门
//            UserDTO userDto = (UserDTO) redisTemplate.opsForValue().get(RedisConstants.ACCOUNT_QUERY_KEY + item.getCreateId());
            UserDTO userDto = sysUserService.queryCacheUser(item.getCreateId());
            if (userDto != null){
                dto.setCreateUserName(userDto.getFullName());
                dto.setCreateUserDept(userDto.getDept());
            }
            //应收金额
            List<CheckAmountStaticsDTO> staticsDTOList =  billCheckDetailMapper.selectSumByCheck(item.getId());
            if (staticsDTOList != null && staticsDTOList.size() > 0){
                staticsDTOList.forEach(statics -> {
                    if (statics.getCollectAmount() == null){
                        statics.setCollectAmount(BigDecimal.ZERO);
                    }
                    if (statics.getRefundAmount() == null){
                        statics.setRefundAmount(BigDecimal.ZERO);
                    }
                    BigDecimal resultAmount = statics.getCollectAmount().subtract(statics.getRefundAmount());
                    statics.setResultAmount(resultAmount);
                    statics.setType(resultAmount.compareTo(BigDecimal.ZERO) >= 0?1:2);
                });
                dto.setStaticsDTOList(staticsDTOList);
                //未收金额
                List<OnAccountUsageCountDTO> usageCountList = onAccountUsageRecordMapper.selectSumByAccount(item.getCustomerId());
                dto.setUsageCountList(usageCountList);
                //已收金额
                List<OnAccountUsageCountDTO> offAccountList = offAccountApplyDetailMapper.selectSumByAccount(item.getCustomerId());
                dto.setOffAccountList(offAccountList);
            }
            list.add(dto);
        });
        PageResponse<BillCheckListDTO> result = new PageResponse<>(
                list,
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 新增
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(BillCheckAddReq req) {
        if (req.getIdList().size() == 0){
            throw new BusinessException(SystemError.SYS_409,"ID集合不能为空");
        }
        //新增客户对账
        FinanceBillCheck check = EntityUtil.copy(req,FinanceBillCheck.class);
        check.setId(SnowflakeIdWorker.nextId());
        check.setCreateId(req.getUserId());
        LocalDateTime now = LocalDateTime.now();
        //过滤财务收退款ID列表
        List<FinanceBill> billList = billMapper.selectBatchIds(req.getIdList());
        List<FinanceBillCheckDetail> checkDetailList = new ArrayList<>();
        if (billList != null && billList.size() > 0){
            billList.forEach(bill -> {
                if (Objects.equals(bill.getIsDeleted(),0) && Objects.equals(bill.getCheckBillStatus(),0)){
                    FinanceBillCheckDetail checkDetail = billCheckDetailMapper.queryByBillId(bill.getId());
                    if (checkDetail == null){
                        //新增对账明细
                        checkDetail = EntityUtil.copy(bill,FinanceBillCheckDetail.class);
                        checkDetail.setId(SnowflakeIdWorker.nextId());
                        checkDetail.setCheckId(check.getId());
                        checkDetail.setBillId(bill.getId());
                        checkDetail.setPayWayId(bill.getCollectionWayId());
                        checkDetail.setPayWay(bill.getCollectionWayName());
                        checkDetail.setSaleOrderId(bill.getSaleOrderId());
                        checkDetail.setResourceInfo(bill.getResourceInfo());
                        checkDetail.setTotalAmount(bill.getCollectionAmount());
                        checkDetail.setGmtCreate(now);
                        checkDetail.setCreateId(req.getUserId());
                        checkDetail.setModifiedId(null);
                        checkDetail.setGmtModified(null);
                        checkDetail.setIsDeleted(0);
                        checkDetailList.add(checkDetail);
                        //更新认款单状态
                        bill.setCheckBillStatus(1);
                        bill.setModifiedId(req.getUserId());
                        int update = billMapper.updateById(bill);
                        if (update <= 0){
                            throw new BusinessException(SystemError.SYS_408);
                        }
                    }
                }
            });
        }
        if (checkDetailList.size() == 0){
            throw new BusinessException(SystemError.FINANCE_BILL_17008);
        }
        //对账单号 KDZ+年後2位+月日4位+時分秒6位+4位随机数字
        String checkNumber = "KDZ"+ DateUtil.fmt(now,"yyMMddHHmmss")+ CharUtil.getRandomStr(4);
        check.setCheckNumber(checkNumber);
        //附件
        if (req.getFilesJson() != null && req.getFilesJson().size() > 0){
            String fileJson = JSON.toJSONString(req.getFilesJson());
            check.setFilesJson(fileJson);
        }
        check.setApprovalStatus(req.getType());
        check.setGmtCreate(now);
        check.setIsDeleted(0);
        //新增对账
        boolean save = save(check);
        //批量新增对账明细
        Integer batchSave = billCheckDetailMapper.insertBatchSomeColumn(checkDetailList);
        if (!save || batchSave < checkDetailList.size()){
            throw new BusinessException(SystemError.SYS_437);
        }
        if (Objects.equals(req.getType(),2)){
            //发起审批
            Long approvalId = startApproval(check.getId(), check.getId(), req.getUserId());
            check.setApprovalId(approvalId);
            boolean update1 = updateById(check);
            if (!update1){
                throw new BusinessException(SystemError.SYS_437);
            }
        }
        return Result.success(check.getId());
    }

    /**
     * 批量删除
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result del(BillCheckDelReq req) {
        if (req.getIdList().size() == 0){
            throw new BusinessException(SystemError.SYS_409,"ID集合不能为空");
        }
        //批量删除
        try {
            billCheckMapper.batchDel(req.getIdList(), req.getUserId());
            billCheckDetailMapper.batchDel(req.getIdList(), req.getUserId());
        }catch (Exception e){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success();
    }

    /**
     * 详情
     *
     * @param req
     * @return
     */
    @Override
    public Result<BillCheckDetailDTO> detail(BillCheckDetailReq req) {
        FinanceBillCheck check = getById(req.getId());
        if (check == null || Objects.equals(check.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17010);
        }
        BillCheckDetailDTO dto = EntityUtil.copy(check, BillCheckDetailDTO.class);
        //附件
        if (StringUtils.isNotBlank(check.getFilesJson())){
            List<FileJson> fileJsons = JSON.parseArray(check.getFilesJson(), FileJson.class);
            dto.setFilesJson(fileJsons);
        }
        if (check.getCreateId() != null){
            UserDTO userDTO = sysUserService.queryCacheUser(check.getCreateId());
            if (userDTO != null){
                dto.setCreateUserName(userDTO.getFullName());
                dto.setCreateUserDept(userDTO.getDept());
            }
        }
        //客户信息
        QueryWrapper<FinanceOnAccount> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account_id",check.getCustomerId());
        queryWrapper.eq("is_deleted",0);
        FinanceOnAccount onAccount = onAccountMapper.selectOne(queryWrapper);
        ClientInfoJson accountJson = new ClientInfoJson();
        accountJson.setAccountId(onAccount.getAccountId());
        accountJson.setAccountName(onAccount.getAccountName());
        accountJson.setBankAccount(onAccount.getBankAccount());
        accountJson.setContactEmail(onAccount.getContactEmail());
        accountJson.setContactName(onAccount.getContactName());
        accountJson.setContactMobile(onAccount.getContactMobile());
        accountJson.setLocation(onAccount.getLocation());
        dto.setAccountJson(accountJson);
        //币种金额统计
        List<CheckAmountStaticsDTO> staticsDTOList = billCheckDetailMapper.selectSumByCheck(check.getId());
        dto.setStaticsDTOList(staticsDTOList);
        return Result.success(dto);
    }

    /**
     * 修改
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result update(BillCheckUpdateReq req) {
        FinanceBillCheck check = getById(req.getId());
        if (check == null || Objects.equals(check.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_BILL_17010);
        }
        if (Objects.equals(check.getApprovalStatus(),2) || Objects.equals(check.getApprovalStatus(),3)){
            throw new BusinessException(SystemError.FINANCE_BILL_17011);
        }
        //过滤财务收退款ID列表
        List<FinanceBill> billList = billMapper.selectBatchIds(req.getIdList());
        List<FinanceBillCheckDetail> checkDetailList = new ArrayList<>();
        if (billList != null && billList.size() > 0){
            billList.forEach(bill -> {
                if (Objects.equals(bill.getIsDeleted(),0) && Objects.equals(bill.getCheckBillStatus(),0)){
                    //新增对账明细
                    FinanceBillCheckDetail checkDetail = EntityUtil.copy(bill,FinanceBillCheckDetail.class);
                    checkDetail.setId(SnowflakeIdWorker.nextId());
                    checkDetail.setCheckId(req.getId());
                    checkDetail.setBillId(bill.getId());
                    checkDetail.setGmtCreate(LocalDateTime.now());
                    checkDetail.setCreateId(req.getUserId());
                    checkDetail.setModifiedId(null);
                    checkDetail.setGmtModified(null);
                    checkDetail.setIsDeleted(0);
                    checkDetailList.add(checkDetail);
                }
            });
        }
        if (checkDetailList.size() == 0){
            throw new BusinessException(SystemError.FINANCE_BILL_17008);
        }
        //更新
        check = EntityUtil.copy(req,FinanceBillCheck.class);
        check.setModifiedId(req.getUserId());
        check.setApprovalStatus(req.getType());
        boolean update = updateById(check);
        //批量删除对账单明细
        billCheckDetailMapper.cleanByCheck(check.getId(),req.getUserId());
        //新增对账单明细
        Integer batchSave = billCheckDetailMapper.insertBatchSomeColumn(checkDetailList);
        if (!update || batchSave < checkDetailList.size()){
            throw new BusinessException(SystemError.SYS_437);
        }
        if (Objects.equals(req.getType(),2)){
            //发起审批
            Long approvalId = startApproval(check.getId(), check.getId(), req.getUserId());
            check.setApprovalId(approvalId);
            boolean update1 = updateById(check);
            if (!update1){
                throw new BusinessException(SystemError.SYS_437);
            }
        }
        return Result.success(check.getId());
    }

    /**
     * 审批
     *
     * @param req
     * @return
     */
    @Override
    public Result approval(BillCheckApprovalReq req) {
        QueryWrapper<FinanceBillCheck> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("approval_id",req.getApprovalId());
        queryWrapper.eq("is_deleted",0);
        FinanceBillCheck check = billCheckMapper.selectOne(queryWrapper);
        if (check == null){
            throw new BusinessException(SystemError.FINANCE_BILL_17010);
        }
        //状态判断
        if (!Objects.equals(check.getApprovalStatus(),2)){
            throw new BusinessException(SystemError.FINANCE_BILL_17012);
        }
        //更新对账单
        check.setApprovalStatus(req.getType());
        check.setModifiedId(req.getUserId());
        boolean update = updateById(check);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        Result<ApprovalCheckDTO> check1 = sysApprovalService.check(req.getApprovalId(), req.getUserId(), req.getType(), req.getComments());
        if (check1 == null || !check1.getData().getIsFinish()){
            throw new BusinessException(SystemError.SYS_437);
        }
        if (Objects.equals(req.getType(),3)){
            //审批通过后的处理
            //查询对账单关联的认款单ID列表
            List<FinanceBill> billList = billCheckDetailMapper.queryBillIdByCheck(check.getId());
            if (billList != null && billList.size() > 0){
                billList.forEach(bill -> {
                    //更新财务收退款记录
                    bill.setCheckBillStatus(1);
                    bill.setModifiedId(req.getUserId());
                    int updateBill = billMapper.updateById(bill);
                    if (updateBill <= 0){
                        throw new BusinessException(SystemError.SYS_437);
                    }
                });
            }
        }
        return Result.success(check.getId());
    }

    /**
     * 往来明细列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<BillCheckDetailListDTO>> detailList(BillCheckDetailListReq req) {
        Page<BillCheckDetailListDTO> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        Page<BillCheckDetailListDTO> page = billMapper.selectByCondition(iPage,req);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        page.getRecords().forEach(item -> {
            item.setCollectionTime(item.getGmtCreate());
            //销售
            if (item.getSaleUserId() != null){
                UserDTO userDto = sysUserService.queryCacheUser(item.getSaleUserId());
                if (userDto != null){
                    item.setSaleDept(userDto.getDept());
                }
            }
        });
        PageResponse<BillCheckDetailListDTO> result = new PageResponse<>(
                page.getRecords(),
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 对账单详情-对账明细列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<BillCheckDetailListDTO>> checkDetailList(BillCheckIdDetailListReq req) {
        Page<BillCheckDetailListDTO> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        Page<BillCheckDetailListDTO> page = billCheckDetailMapper.selectByCheck(iPage,req.getCheckId());
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        page.getRecords().forEach(item -> {
            item.setCollectionTime(item.getGmtCreate());
            //销售
            UserDTO userDto = sysUserService.queryCacheUser(item.getSaleUserId());
            if (userDto != null){
                item.setSaleDept(userDto.getDept());
            }
        });
        PageResponse<BillCheckDetailListDTO> result = new PageResponse<>(
                page.getRecords(),
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 撤回审批
     *
     * @param req
     * @return
     */
    @Override
    public Result rollBack(RollBackReq req) {
        QueryWrapper<FinanceBillCheck> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("approval_id",req.getApprovalId());
        queryWrapper.eq("is_deleted",0);
        FinanceBillCheck check = billCheckMapper.selectOne(queryWrapper);
        if (check == null){
            throw new BusinessException(SystemError.FINANCE_BILL_17010);
        }
        if (!Objects.equals(check.getCreateId(),req.getUserId())){
            throw new BusinessException(SystemError.FINANCE_ERROR_17039);
        }
        check.setApprovalId(null);
        check.setApprovalStatus(1);
        check.setModifiedId(req.getUserId());
        boolean update = updateById(check);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success();
    }


    /**
     * 发起审批流程
     * @param id
     * @param businessId
     * @param userId
     */
    private Long startApproval(Long id, Long businessId, Long userId) {
        Map<String, Object> extendParams = new HashMap<>();
        extendParams.put("id", id);
        try{
            Result<ApprovalStartDTO> approvalResult = sysApprovalService.start(SystemBusinessType.FINANCE.getCode(),
                    SysApprovalType.PAIRS_FINANCE.getCode(), businessId,
                    userId, null, JSON.toJSONString(extendParams));
            if (!approvalResult.isSuccess()) {
                throw new BusinessException(SystemError.CUSTOM_ORDER_4044);
            }
            return approvalResult.getData().getApprovalId();
        }catch (Exception e){
            throw new BusinessException(SystemError.SYS_422);
        }
    }


}
